home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 3.0a2 / Libraries / UPrinting.cp < prev    next >
Encoding:
Text File  |  1991-05-01  |  62.5 KB  |  2,316 lines  |  [TEXT/MPS ]

  1. // UPrinting.cp
  2. // Copyright © 1986-1991 by Apple Computer, Inc.  All rights reserved.
  3.  
  4. /*
  5.   Segmentation strategy:
  6.   PrintRes  Resident
  7.   PrintMain Resident and used at initialization
  8.   PrintActual Used only during Actual Printing (imaging/spooling)
  9.   PrintImage    Used during imaging only
  10.   PrintSpool    Used only during printing of a Spool File
  11.   PrintDebug    Debugging code
  12.   PrintFinder Code only ever accessed from Finder Printing
  13.   PrintInit One-time Initialization Code
  14.   PrintOpen Code accessed when opening new document
  15.   PrintNonRes General non-resident code
  16.   PrintDoCommand   Code for Page Setup command
  17.   PrintTerminate   One-time-only code, called only at Termination time
  18. */
  19.  
  20. #ifndef __UGEOMETRY__
  21. #include <UGeometry.h>
  22. #endif
  23.  
  24. #ifndef __ULIST__
  25. #include <UList.h>
  26. #endif
  27.  
  28. #ifndef __EDITIONS__
  29. #include <Editions.h>
  30. #endif
  31.  
  32. #ifndef __UAPPLICATION__
  33. #include <UApplication.h>
  34. #endif
  35.  
  36. #ifndef __UDOCUMENT__
  37. #include <UDocument.h>
  38. #endif
  39.  
  40. #ifndef __BALLOONS__
  41. #include <Balloons.h>
  42. #endif
  43.  
  44. #ifndef __UVIEW__
  45. #include <UView.h>
  46. #endif
  47.  
  48. #ifndef __UWINDOW__
  49. #include <UWindow.h>
  50. #endif
  51.  
  52. #ifndef __UFAILURE__
  53. #include <UFailure.h>
  54. #endif
  55.  
  56. #ifndef __UMACAPPUTILITIES__
  57. #include <UMacAppUtilities.h>
  58. #endif
  59.  
  60. #ifndef __UERRORMGR__
  61. #include <UErrorMgr.h>
  62. #endif
  63.  
  64. #ifndef __UPATCH__
  65. #include <UPatch.h>
  66. #endif
  67.  
  68. #ifndef __UMEMORY__
  69. #include <UMemory.h>
  70. #endif
  71.  
  72. #ifndef __UMACAPPGLOBALS__
  73. #include <UMacAppGlobals.h>
  74. #endif
  75.  
  76. #ifndef __MENUS__
  77. #include <Menus.h>
  78. #endif
  79.  
  80. #ifndef __UMENUMGR__
  81. #include <UMenuMgr.h>
  82. #endif
  83.  
  84. #ifndef __TOOLUTILS__
  85. #include <ToolUtils.h>
  86. #endif
  87.  
  88. #ifndef __PACKAGES__
  89. #include <Packages.h>
  90. #endif
  91.  
  92. #ifndef __FONTS__
  93. #include <Fonts.h>
  94. #endif
  95.  
  96. #ifndef __ERRORS__
  97. #include <Errors.h>
  98. #endif
  99.  
  100. #ifndef __RESOURCES__
  101. #include <Resources.h>
  102. #endif
  103.  
  104. #ifndef __STDLIB__
  105. #include <StdLib.h>
  106. #endif
  107.  
  108. #ifndef __STDIO__
  109. #include <StdIo.h>
  110. #endif
  111.  
  112. #ifndef __UPRINTING__
  113. #include <UPrinting.h>
  114. #endif
  115.  
  116. //--------------------------------------------------------------------------------------------------
  117. PenState gBreaksPenState;
  118. Boolean gCancelAllPrinting;
  119. VRect gStdPageMargins;
  120. Handle gFinderHPrint;
  121. TStdPrintHandler* gJobPrintHandler;
  122.  
  123. //--------------------------------------------------------------------------------------------------
  124.  
  125. // subclass may stuff some special values by redefining this 
  126. union TXWord
  127. {
  128.     struct
  129.     {
  130.         char c1, c0;
  131.     } charVal;
  132.     struct
  133.     {
  134.         SignedByte b1, b0;
  135.     } byteVal;
  136.     struct
  137.     {
  138.         Boolean f15, f14, f13, f12, f11, f10, f9, f8, f7, f6, f5, f4, f3, f2, f1, f0;
  139.     } boolVal;
  140.     short iO;
  141. };
  142.  
  143. //--------------------------------------------------------------------------------------------------
  144. #pragma segment PrintRes
  145.  
  146. pascal void TPrintCommand::DoIt(void)
  147. {
  148.     Boolean proceed;
  149.  
  150.     fStdPrintHandler->Print(fID, proceed);
  151. }
  152.  
  153. //--------------------------------------------------------------------------------------------------
  154. #pragma segment PrintSelCommand
  155.  
  156. pascal void TPrintCommand::Initialize(void)        // override 
  157. {
  158.     inherited::Initialize();
  159.     fStdPrintHandler = NULL;
  160. }
  161.  
  162. //--------------------------------------------------------------------------------------------------
  163. #pragma segment PrintSelCommand
  164.  
  165. pascal void TPrintCommand::IPrintCommand(CmdNumber itsCmdNumber,
  166.                                          TStdPrintHandler* itsStdPrintHandler)
  167. {
  168.     this->INoChangesCommand(itsCmdNumber, itsStdPrintHandler->fDocument, itsStdPrintHandler->fView);
  169.     fStdPrintHandler = itsStdPrintHandler;
  170. }
  171.  
  172. //--------------------------------------------------------------------------------------------------
  173. #pragma segment MAFields
  174.  
  175. pascal void TPrintCommand::Fields(TObject* obj)    // override 
  176. {
  177.     obj->DoToField("TPrintCommand", NULL, bClass);
  178.     obj->DoToField("fStdPrintHandler", &fStdPrintHandler, bObject);
  179.     inherited::Fields(obj);
  180. }
  181.  
  182. //--------------------------------------------------------------------------------------------------
  183. #pragma segment PrintActual
  184. //$Push
  185. // #if qTrace
  186. //$D+
  187. //#endif  No tracing till we get the port straightened out since the current
  188. //port could already be disposed (Thank you Direct connect ImageWriter!)
  189.  
  190. pascal void IdleProcForTStdPrintHandler(void)
  191. {
  192.     GrafPtr savedPort;
  193.  
  194.     if (gJobPrintHandler)
  195.     {
  196.         GetPort(savedPort);
  197.         SetPort(gWorkPort);                        // Nice safe port in a storm 
  198.         gJobPrintHandler->DoPrintIdling();        // Forward to the current print job handler 
  199.         SetPort(savedPort);
  200.     }
  201. }
  202. //$Pop
  203.  
  204. //--------------------------------------------------------------------------------------------------
  205. #pragma segment PrintActual
  206.  
  207. pascal void TStdPrintHandler::DoPrintIdling(void)
  208. {
  209.     const short myDlgMask = mDownMask + mUpMask + keyDownMask + keyUpMask + autoKeyMask;
  210.  
  211.     char ch;
  212.     short keycode;
  213.     DialogPtr aDialog;
  214.     TToolboxEvent * event;
  215.     EventRecord anEventRecord;
  216.     short item;
  217.     Handle theItem;
  218.     short itemType;
  219.     Rect box;
  220.     long dontCare;
  221.  
  222.     event = gApplication->GetEvent(myDlgMask, 0, NULL);
  223.     if (event)
  224.     {
  225.         // Workaround for LaserWriter driver bug: it tries to set GhostWindow
  226.         // so that its status window is invisible. Unfortunately, it doesn't
  227.         // always set it, so IsDialogEvent returns FALSE (the status window
  228.         // is frontmost).  If ours isn't already in front, force it there.
  229.         if (fPrintDialog != FrontWindow())
  230.             gApplication->SelectWMgrWindow(fPrintDialog);
  231.  
  232.         switch (event->fEventRecord.what)
  233.         {
  234.             case keyDown:
  235.                 ch = (char)(event->fEventRecord.message & charCodeMask);
  236.                 keycode = (short)((event->fEventRecord.message >> keyCodeMask) & 8);
  237.                 if (((ch == '.') && event->fCmdKey) || ((ch == chEscape) && (keycode == kEscapeVirtualCode)))
  238.                 {
  239.  
  240.                     /*### need a way to determine if multiple file printing is in process
  241.                       if (gFinderPrinting)
  242.                       item = cancel;                -- Want the 'Cancel All' button 
  243.                       else
  244.                       item = 1;                    -- Want the 'Cancel' button 
  245.                     */
  246.                     item = 1;
  247.  
  248.                     // Flash the appropriate button 
  249.                     GetDItem(fPrintDialog, item, itemType, theItem, box);
  250.                     HiliteControl((ControlHandle)theItem, 10);
  251.                     Delay(8, dontCare);
  252.                     HiliteControl((ControlHandle)theItem, 0);
  253.  
  254.                     PrSetError(iPrAbort);
  255.                     gCancelAllPrinting = TRUE;
  256.                 }
  257.                 break;
  258.  
  259.             default:
  260.                 anEventRecord = event->fEventRecord;
  261.                 if (IsDialogEvent(anEventRecord) && DialogSelect(anEventRecord, aDialog, item) && (aDialog == fPrintDialog))
  262.                     switch (item)
  263.                     {
  264.                         case 1:
  265.                             PrSetError(iPrAbort);// Cancel
  266.                             break;
  267.  
  268.                         case cancel:            // Cancel All Printing 
  269.                             PrSetError(iPrAbort);
  270.                             gCancelAllPrinting = TRUE;
  271.                             break;
  272.                     }
  273.                 break;
  274.         }
  275.     }
  276. }
  277.  
  278. //--------------------------------------------------------------------------------------------------
  279. #pragma segment PrintActual
  280.  
  281. pascal void TStdPrintHandler::ChkPrintErr(OSErr& err,
  282.                                           Boolean& proceed,
  283.                                           Boolean& ranOutOfSpace)
  284. {
  285.     if (proceed)
  286.     {
  287.         err = PrError();
  288.         if (err != noErr)
  289.         {
  290. #if qDebugMsg
  291.             if (gDebugPrinting)
  292.                 fprintf(stderr, "Error from PrError is %d\n", err);
  293. #endif
  294.  
  295.             proceed = FALSE;
  296.             if (err == -1)
  297.                 ranOutOfSpace = TRUE;
  298.         }
  299.     }
  300. }
  301.  
  302. //--------------------------------------------------------------------------------------------------
  303. #pragma segment PrintRes
  304.  
  305. pascal void TStdPrintHandler::GetDriverName(Str255& driverName)
  306. {
  307.     String255Handle driverHandle;
  308.  
  309.     driverHandle = (String255Handle)GetString((short)kPrintDriverName);// Get current driver 
  310.  
  311.     // Be a little cautious, in case we accidentally pick up something
  312.     // which is not what we expect, or we can't find it.
  313.     if (driverHandle && ((**driverHandle).Length() < 64))
  314.         CopyStr255(**driverHandle, (Ptr) & driverName);
  315.     else
  316.         driverName = "";
  317. }
  318.  
  319. //--------------------------------------------------------------------------------------------------
  320. #pragma segment PrintInit
  321. // Initialize the printing unit.  Call exactly once 
  322.  
  323. pascal void InitUPrinting(void)
  324. {
  325.     TStdPrintHandler * aStdPrintHandler;
  326.  
  327.     gCancelAllPrinting = FALSE;
  328.     gFinderHPrint = NULL;
  329.     gJobPrintHandler = NULL;
  330.  
  331.     gStdPageMargins = VRect(72, 72, -72, -72);// 1" margins std default
  332.  
  333.     gBreaksPenState.pnLoc = gZeroPt;
  334.     gBreaksPenState.pnSize = Point(2, 2);
  335.     gBreaksPenState.pnMode = patCopy;
  336.     StuffHex(gBreaksPenState.pnPat, "CC663399CC663399");
  337.  
  338.     gCouldPrint = TRUE;
  339.  
  340.     gUPrintingInitialized = TRUE;
  341.  
  342.     if (gPrintHandler == gNullPrintHandler)
  343.     {
  344.         // Install a StdPrintHandler in UMacApp
  345.         // global variable gPrintHandler
  346.         aStdPrintHandler = new TStdPrintHandler;
  347.         aStdPrintHandler->IStdPrintHandler(NULL, NULL, kSquareDots, kFixedSize, kFixedSize);
  348.         aStdPrintHandler->fFinderJobDialog = TRUE;
  349.         gPrintHandler = aStdPrintHandler;
  350.     }
  351. }
  352.  
  353. //--------------------------------------------------------------------------------------------------
  354. #pragma segment MAPrintingRes
  355. // Synonym For InitUPrinting 
  356.  
  357. pascal void InitPrinting(void)
  358. {
  359.     InitUPrinting();
  360. }
  361.  
  362. //--------------------------------------------------------------------------------------------------
  363. #pragma segment PrintSpool
  364.  
  365. pascal void TStdPrintHandler::PrintSpoolFile(Handle anHPrint,
  366.                                              OSErr& err,
  367.                                              Boolean& proceed)
  368. {
  369.     TPrStatus prStatus;
  370.     Boolean b;
  371.  
  372.     proceed = TRUE;
  373.     PrPicFile((THPrint)anHPrint, NULL, NULL, NULL, prStatus);
  374.     this->ChkPrintErr(err, proceed, b);
  375. }
  376.  
  377. //--------------------------------------------------------------------------------------------------
  378. #pragma segment PrintOpen
  379.  
  380. pascal void TStdPrintHandler::Initialize(void)    // override 
  381. {
  382. #if qDebug
  383.     if (!gUPrintingInitialized)
  384.     {
  385.         ProgramBreak("InitUPrinting must be called before creating a print handler.");
  386.         Failure(noErr, 0);
  387.     }
  388. #endif
  389.  
  390.     inherited::Initialize();
  391.     fFinderJobDialog = FALSE;
  392.     fFinderSetup = FALSE;
  393.     fFixedSizePages[hSel] = kFixedSize;
  394.     fFixedSizePages[vSel] = kFixedSize;
  395.     fHPrint = NULL;
  396.     fLastBreak = gZeroVPt;
  397.     fLastPrinterName = NULL;
  398.     fLastStrip = VPoint(MAXINT, MAXINT);
  399.     fMarginRes = Point(72, 72);
  400.     fMinimalMargins = FALSE;
  401.     fPageAreas.theMargins = gStdPageMargins;    //!!! What about other fields of fPageAreas? 
  402.     fPageDirection = vSel;                        // Page 2 is below page 1, etc. 
  403.     fPageStrips = gZeroVPt;                        //!!! Another default? 
  404.     fPPrPort = NULL;
  405.     fPrintDialog = NULL;
  406.     fPrinterDev = kNeverInitialized;
  407.     fPrintExtent = gZeroVRect;                    //!!! Another default? 
  408.     fShowBreaks = FALSE;
  409.     fSquareDots = kSquareDots;
  410.     fStartPage = 1;
  411.     fViewedRect = gZeroVRect;                    //!!! Another default? 
  412.  
  413. }
  414.  
  415. //--------------------------------------------------------------------------------------------------
  416. #pragma segment PrintOpen
  417.  
  418. pascal void TStdPrintHandler::IStdPrintHandler(TDocument* itsDocument,
  419.                                                TView* itsView,
  420.                                                Boolean itsSquareDots,
  421.                                                Boolean itsHFixedSize,
  422.                                                Boolean itsVFixedSize)
  423. {
  424.     FailInfo fi;
  425.  
  426.     this->IPrintHandler(itsView);                // sets fView to itsView
  427.  
  428.     fDocument = itsDocument;
  429.     fSquareDots = itsSquareDots;
  430.     fFixedSizePages[hSel] = itsHFixedSize;
  431.     fFixedSizePages[vSel] = itsVFixedSize;
  432.  
  433.     if (fi.Try())
  434.     {
  435.         if (fView)
  436.         {
  437.             // allocates a handle for the print-info, and sets my field fHPrint accordingly 
  438.             this->SetDefaultPrintInfo();
  439.  
  440.             if (itsDocument)
  441.                 itsDocument->AttachPrintHandler(this);
  442.  
  443.             fView->AttachPrintHandler(this);
  444.         }
  445.         fi.Success();
  446.     }
  447.     else    // Recover
  448.     {
  449.         this->Free();
  450.         fi.ReSignal();
  451.     }
  452. }
  453.  
  454. //--------------------------------------------------------------------------------------------------
  455. #pragma segment PrintClose
  456.  
  457. pascal void TStdPrintHandler::Free(void)        // override 
  458. {
  459.     Boolean dontDispose = (fView != NULL);
  460.     if (dontDispose)
  461.     {
  462.         if (fView->fPrintHandler == this)
  463.             fView->fPrintHandler = NULL;        // was fView->AttachPrintHandler(gNullPrintHandler);
  464.         fView = NULL;
  465.  
  466.         TDocument * itsDocument = fDocument;
  467.         dontDispose = (itsDocument != NULL);
  468.         if (dontDispose)
  469.         {
  470.             itsDocument->DetachPrintHandler(this);
  471.             dontDispose = itsDocument->fSharePrintInfo;
  472.         }
  473.         if (dontDispose)
  474.             dontDispose = (itsDocument->fPrintInfo == fHPrint);
  475.         fDocument = NULL;
  476.     }
  477.  
  478.     if (!dontDispose)
  479.         fHPrint = DisposeIfHandle(fHPrint);
  480.     fHPrint = NULL;                                // Always drop my reference 
  481.  
  482.     fLastPrinterName = (StringHandle)DisposeIfHandle((Handle)fLastPrinterName);
  483.  
  484.     this->BanishPrintDialog();
  485.  
  486.     if (gJobPrintHandler == this)                // let's be safe 
  487.         gJobPrintHandler = NULL;
  488.  
  489.     inherited::Free();
  490. }
  491.  
  492. //--------------------------------------------------------------------------------------------------
  493. #pragma segment PrintRes
  494.  
  495. pascal TObject* TStdPrintHandler::Clone(void)    // Override
  496. {
  497.     TStdPrintHandler* aStdPrintHandler;
  498.     Handle aHandle;
  499.     FailInfo fi;
  500.     OSErr err;
  501.  
  502.     VOLATILE(aStdPrintHandler);
  503.  
  504.     aStdPrintHandler = (TStdPrintHandler *)(inherited::Clone());
  505.     
  506.     if (fHPrint)
  507.     {
  508.         aStdPrintHandler->fHPrint = NULL;
  509.         if (fi.Try())
  510.         {
  511.             aHandle = fHPrint;
  512.             err = HandToHand(aHandle);
  513.             if (err != noErr)
  514.                 FailNIL(aHandle);
  515.             aStdPrintHandler->fHPrint = aHandle;
  516.             fi.Success();
  517.         }
  518.         else    // Recover
  519.         {
  520.             aStdPrintHandler->Free();
  521.             fi.ReSignal();
  522.         }
  523.     }
  524.     
  525.     if (fLastPrinterName)
  526.     {
  527.         aStdPrintHandler->fLastPrinterName = NULL;
  528.         if (fi.Try())
  529.         {
  530.             aHandle = (Handle)fLastPrinterName;
  531.             err = HandToHand(aHandle);
  532.             if (err != noErr)
  533.                 FailNIL(aHandle);
  534.             aStdPrintHandler->fLastPrinterName = (StringHandle)aHandle;
  535.             fi.Success();
  536.         }
  537.         else    // Recover
  538.         {
  539.             aStdPrintHandler->Free();
  540.             fi.ReSignal();
  541.         }
  542.     }
  543.     
  544.     fPrintDialog = NULL;                // Sorry, but this just can't be cloned
  545.     
  546.     return aStdPrintHandler;
  547. }
  548.  
  549. //--------------------------------------------------------------------------------------------------
  550. #pragma segment PrintImage
  551.  
  552. pascal void TStdPrintHandler::AdornPage(void)
  553. {
  554. #if qDebug
  555.     const short botSlop = 8;                    // ??? Arbitrary choice 
  556.  
  557.     Str255 heading;
  558.     Str255 pgStr;
  559.     VRect handyRect;
  560.     Rect handyQDRect;
  561.     long itsWidth;
  562.     long rPlusL;
  563.     long itsBottom;
  564.     FontInfo theFontInfo;
  565.     Rect theTextRect;
  566.  
  567.     if (gDebugPrinting)                            // Print extra stuff if debugging 
  568.     {
  569.         NumToString(fFocusedPage, pgStr);
  570.         TextFont(applFont);
  571.         TextFace(normal);
  572.         TextSize(12);
  573.         heading = "-" + pgStr + "-";            // ??? Make easier for client to change this
  574.  
  575.         // draw the heading
  576.         itsWidth = StringWidth(heading);
  577.         rPlusL = fPageAreas.thePaper.right + fPageAreas.thePaper.left;
  578.         itsBottom = fPageAreas.theInk.bottom - botSlop;
  579.         GetFontInfo(theFontInfo);
  580.         theTextRect.left = (short)(rPlusL - itsWidth) / 2;
  581.         theTextRect.top = (short)itsBottom - theFontInfo.ascent;
  582.         theTextRect.right = (short)(theTextRect.left + itsWidth);
  583.         theTextRect.bottom = (short)itsBottom + theFontInfo.descent;
  584.         MADrawString(heading, theTextRect, teFlushDefault);
  585.  
  586.         // Additionally frame the printable area of the page if gDebugPrinting 
  587.         handyRect = fPageAreas.theInk;
  588.         fView->ViewToQDRect(handyRect, handyQDRect);
  589.  
  590.         PenSize(1, 1);
  591.         FrameRect(handyQDRect);
  592.  
  593.         // Frame the 'interior' of the page 
  594.         handyRect = fPageAreas.theInterior;
  595.         fView->ViewToQDRect(handyRect, handyQDRect);
  596.  
  597.         PenSize(2, 2);
  598.         FrameRect(handyQDRect);
  599.     }
  600. #endif
  601.  
  602. }
  603.  
  604. //--------------------------------------------------------------------------------------------------
  605. #pragma segment PrintActual
  606.  
  607. pascal void TStdPrintHandler::BanishPrintDialog(void)
  608. {
  609.     if (fPrintDialog)
  610.     {
  611.         if (fPrintDialog == qd.thePort)            // Only need to invalidate focus if freed
  612.         // dialog is the current port
  613.         {
  614.             gApplication->InvalidateFocus();
  615.             SetPort(gWorkPort);
  616.         }
  617.         DisposDialog(fPrintDialog);
  618.         fPrintDialog = NULL;
  619.     }
  620. }
  621.  
  622. //--------------------------------------------------------------------------------------------------
  623. #pragma segment PrintRes
  624.  
  625. // Called from fView->DoBreakFollowing(), 
  626. pascal VCoordinate TStdPrintHandler::BreakFollowing(VHSelect vhs,
  627.                                                     VCoordinate prevBreak,
  628.                                                     Boolean& automatic)// override 
  629. {
  630.     VHSelect orthoVHS;
  631.     VCoordinate newLoc;
  632.  
  633.     orthoVHS = gOrthogonal[vhs];
  634.     automatic = TRUE;
  635.     newLoc = Min(prevBreak + fViewPerPage[orthoVHS], fPrintExtent[botRight][orthoVHS]);
  636.  
  637. #if qDebugMsg
  638.     if (newLoc <= prevBreak)
  639.     {
  640.         fprintf(stderr, "No advance in BreakFollowing; vhs: %1d prevBreak: %1d newLoc: %1d view size: ",
  641.                 (short)vhs, prevBreak, newLoc, fPrintExtent[botRight][orthoVHS]);
  642.         ProgramBreak("No advance in BreakFollowing");
  643.     }
  644. #endif
  645.  
  646.     return newLoc;
  647. }
  648.  
  649. //--------------------------------------------------------------------------------------------------
  650. #pragma segment PrintNonRes
  651.  
  652. pascal Boolean FindLimit(VCoordinate,
  653.                          Boolean,
  654.                          void* staticLink)
  655. {
  656.     ++(*((long*)staticLink));
  657.     return FALSE;
  658. }
  659.  
  660.  
  661. pascal void TStdPrintHandler::CalcPageStrips(VPoint& pageStrips)// override 
  662. {
  663.     VHSelect ortho;
  664.     long nStrips;
  665.  
  666.     // If pages are of fixed size, then simple divide the total size by the
  667.     // page size.  Otherwise, count up the page breaks one by one.
  668.  
  669.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  670.     {
  671.         ortho = gOrthogonal[vhs];
  672.         if (fFixedSizePages[ortho])
  673.             pageStrips[vhs] = (fPrintExtent[botRight][ortho] - fPrintExtent[topLeft][ortho] + fViewPerPage[ortho] - 1) / fViewPerPage[ortho];
  674.         else
  675.         {
  676.             nStrips = 0;
  677.             this->EachBreak(vhs, TRUE, FindLimit, &nStrips);
  678.             pageStrips[vhs] = nStrips;
  679.         }
  680.     }
  681. }
  682.  
  683. //--------------------------------------------------------------------------------------------------
  684. #pragma segment PrintNonRes
  685.  
  686. pascal void TStdPrintHandler::CalcViewPerPage(VPoint& amtPerPage)// override 
  687. {
  688.     VRect paper = fPageAreas.thePaper;
  689.     VRect margins = fPageAreas.theMargins;
  690.     
  691.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  692.     {
  693.         VPoint paperBotRight = paper[botRight];
  694.         VPoint paperTopLeft = paper[topLeft];
  695.         VPoint marginsBotRight = margins[botRight];
  696.         VPoint marginsTopLeft = margins[topLeft];
  697.         long temp = paperBotRight[vhs] - paperTopLeft[vhs] - labs(marginsTopLeft[vhs]) - labs(marginsBotRight[vhs]);
  698.         temp = Max(1, temp);
  699.         amtPerPage[vhs] = temp;
  700.     }
  701. }
  702.  
  703. //--------------------------------------------------------------------------------------------------
  704. #pragma segment PrintRes
  705.  
  706. // this msg is sent to all views if my associated document is the kind where one
  707. // copy of the PrintInfo is shared among all views
  708. pascal void ItChanged(TView* aView,
  709.                       void*)
  710. {
  711.     aView->DoPrinterChanged();
  712. }
  713.  
  714.  
  715. pascal void TStdPrintHandler::CheckPrinter(void)// override 
  716. {
  717.     PageAreas oldPageAreas = fPageAreas;
  718.     long oldPrinterDev = fPrinterDev;
  719.     Point oldDevRes(fDeviceRes);
  720.     Point oldMarginRes(fMarginRes);
  721.     Boolean didChange;
  722.     Boolean msgSent;
  723.     Str255 driverName;
  724.     VRect aRect,  bRect;
  725.  
  726.     // It costs an open and several LoadResources to call PrValidate.  Before
  727.     // doing so, check to see if the printer has actually changed.
  728.     this->GetDriverName(driverName);
  729.     if (!fLastPrinterName || (!EqualString(**fLastPrinterName, driverName, FALSE, TRUE)))
  730.     {
  731.         // Printer name has changed… 
  732.         fLastPrinterName = (StringHandle)DisposeIfHandle((Handle)fLastPrinterName);// out with the old 
  733.         fLastPrinterName = NewString(driverName);// in with the new 
  734.         FailNIL(fLastPrinterName);
  735.         this->ValidatePrintRecord(didChange);    // …and validate the print record. 
  736.     }
  737.  
  738.     // Store latest data from MacPrint prInfo record into my own instance variables
  739.     fPageAreas.thePaper = ((TPPrint) * fHPrint)->rPaper;
  740.     fMarginRes = Point(((TPPrint) * fHPrint)->prInfo.iVRes, ((TPPrint) * fHPrint)->prInfo.iHRes);// read the new device resolution values 
  741.     fDeviceRes = fMarginRes;
  742.     fPrinterDev = ((TPPrint) * fHPrint)->prInfo.iDev;
  743.     fPageAreas.theInk = ((TPPrint) * fHPrint)->prInfo.rPage;
  744.     if (!fMinimalMargins)
  745.         fPageAreas.theMargins = VRect(IntMultiply((short)fPageAreas.theMargins.top, fMarginRes.v) / oldMarginRes.v, IntMultiply((short)fPageAreas.theMargins.left, fMarginRes.h) / oldMarginRes.h, IntMultiply((short)fPageAreas.theMargins.bottom, fMarginRes.v) / oldMarginRes.v, IntMultiply((short)fPageAreas.theMargins.right, fMarginRes.h) / oldMarginRes.h);
  746.  
  747.     aRect = fPageAreas.thePaper;
  748.     bRect = fPageAreas.theInk;
  749.     if ((aRect != oldPageAreas.thePaper) || (bRect != oldPageAreas.theInk) || (fDeviceRes != oldDevRes) || (oldPrinterDev == kNeverInitialized))
  750.     {
  751.         msgSent = FALSE;                        // something important to our projection model changed...
  752.         if (fDocument)
  753.             if (fDocument->fSharePrintInfo)
  754.             {
  755.                 fDocument->ForAllViewsDo(ItChanged, this);
  756.                 msgSent = TRUE;
  757.             }
  758.  
  759.         if (!msgSent)                            // didn't send msg to all views, current company included,
  760.         // so now we need to tell must my local view
  761.             fView->DoPrinterChanged();
  762.     }
  763. }
  764.  
  765. //--------------------------------------------------------------------------------------------------
  766. #pragma segment PrintImage
  767.  
  768. pascal void TStdPrintHandler::ChooseSpoolFile(Str255& spoolFileName,
  769.                                               short& spoolVRefNum,
  770.                                               long& pagesPerSubjob)
  771. {
  772.     spoolFileName = "";                            // Default choices tell MacPrint to use its
  773.     // standard choice algorithm
  774.     spoolVRefNum = 0;
  775.  
  776.     // Print Shop suggests attempting to print entire document.  If it
  777.     // runs out of space, then PerformPrinting will retry with a
  778.     // smaller number of pages.
  779.     pagesPerSubjob = MAXINT;
  780. }
  781.  
  782. //--------------------------------------------------------------------------------------------------
  783. #pragma segment PrintRes
  784.  
  785. pascal void TStdPrintHandler::ClosePrintShop(void)
  786. {
  787.     PrClose();
  788. #if qDebugMsg
  789.     OSErr err = PrError();                            // Now check for fresh error from MacPrint --
  790.     // only for debugging, since ChkPrintErr
  791.     // checks afresh in the real world
  792.     if (err != noErr)
  793.         fprintf(stderr, "Error from MacPrint is: %1d\n", err);
  794. #endif
  795.  
  796. }
  797.  
  798. //--------------------------------------------------------------------------------------------------
  799. #pragma segment PrintRes
  800.  
  801. pascal void TStdPrintHandler::DoInMacPrint(pascal void(* WhatToDo)(void* staticLink),
  802.                                            void* staticLink)
  803. {
  804.     FailInfo fi;
  805.  
  806.     if (gCouldPrint)
  807.     {
  808.         PrSetError(noErr);                        // Clear printer-error flag 
  809.         if (fi.Try())
  810.         {
  811.             this->OpenPrintShop();
  812.             (*WhatToDo)(staticLink);            // Do what needs to be done 
  813.             fi.Success();
  814.         }
  815.         else    // Recover
  816.         {
  817.             this->ClosePrintShop();
  818.             SetPort(gWorkPort);                    // Might be left looking at a dead port 
  819.             gApplication->InvalidateFocus();
  820.             fi.ReSignal();
  821.         }
  822.         this->ClosePrintShop();
  823.         SetPort(gWorkPort);                        // Might be left looking at a dead port 
  824.         gApplication->InvalidateFocus();
  825.     }
  826.     // NB: if gCouldPrint is FALSE, DoInMacPrint is a no-op 
  827. }
  828.  
  829. //--------------------------------------------------------------------------------------------------
  830. #pragma segment PrintRes
  831.  
  832. pascal void TStdPrintHandler::DoMenuCommand(CmdNumber aCmdNumber) // override 
  833. {
  834.     if (!this->DoPrintCommand(aCmdNumber))
  835.         inherited::DoMenuCommand(aCmdNumber);
  836. }
  837.  
  838. //--------------------------------------------------------------------------------------------------
  839. #pragma segment PrintRes
  840.  
  841. pascal Boolean TStdPrintHandler::DoPrintCommand(CmdNumber aCmdNumber)
  842. {
  843.     Boolean proceed;
  844.     Boolean handled = TRUE;                        // assume we handle it
  845.     TPrintCommand * aPrintCommand;
  846.  
  847.     switch (aCmdNumber)
  848.     {
  849.         case cPrint:
  850.             this->CheckPrinter();
  851.             if (this->PoseJobDialog())
  852.             {
  853.                 aPrintCommand = new TPrintCommand;
  854.                 aPrintCommand->IPrintCommand(aCmdNumber, this);
  855.                 if (fOwner)
  856.                     fOwner->PostCommand(aPrintCommand);
  857.                 else
  858.                     gApplication->PostCommand(aPrintCommand);
  859.             }
  860.             break;
  861.  
  862.         case cPrintOne:
  863.             this->CheckPrinter();
  864.             if (this->SetupPrintOne())
  865.             {
  866.                 aPrintCommand = new TPrintCommand;
  867.                 aPrintCommand->IPrintCommand(aCmdNumber, this);
  868.                 if (fOwner)
  869.                     fOwner->PostCommand(aPrintCommand);
  870.                 else
  871.                     gApplication->PostCommand(aPrintCommand);
  872.             }
  873.             break;
  874.  
  875.         case cPageSetup:
  876.             this->PosePageSetupDialog(proceed, TRUE);
  877.             break;
  878.  
  879.         case cShowBreaks:                        // Toggle state of "Show Breaks" 
  880.             fShowBreaks =!fShowBreaks;
  881.             this->InvalPageFeedback();            // force redraw of area the breaks did or will occupy
  882.             break;
  883.  
  884.         case cFinderPrint:                        // handle finder printing 
  885.             proceed = this->SetupForFinder();
  886.             if (proceed)
  887.                 this->Print(cFinderPrint, proceed);
  888.             gFinderPrintingProceed = proceed;
  889.             break;
  890.  
  891.         default:
  892.             handled = FALSE;
  893.             break;
  894.     }
  895.     return handled;
  896. }
  897.  
  898. //--------------------------------------------------------------------------------------------------
  899. #pragma segment PrintRes
  900.  
  901. pascal void TStdPrintHandler::DoSetupMenus(void)    // override 
  902. {
  903.     inherited::DoSetupMenus();
  904.  
  905.     this->DoSetupPrintMenus();
  906. }
  907.  
  908. //--------------------------------------------------------------------------------------------------
  909. #pragma segment PrintRes
  910.  
  911. pascal void TStdPrintHandler::DoSetupPrintMenus(void)
  912. {
  913.     if (gCouldPrint && fView && !MemSpaceIsLow())
  914.     {
  915.         Enable(cPrint, TRUE);
  916.         Enable(cPageSetup, TRUE);
  917.         Enable(cPrintOne, TRUE);
  918.     }
  919.     EnableCheck(cShowBreaks, TRUE, fShowBreaks);
  920. }
  921.  
  922. //--------------------------------------------------------------------------------------------------
  923. #pragma segment PrintRes
  924. // A local class to help iterate over the list of handles and insert into a DescList
  925.  
  926. class CPageBreaks
  927. {
  928.     VHSelect& fOrthoVHS;
  929.     VHSelect& fVHS;
  930.     short& fWhichBreak;
  931.     const VRect& fViewArea;
  932.     TView* fView;
  933.  
  934. public:
  935.     CPageBreaks(VHSelect& theOrthoVHS,
  936.                 VHSelect& theVHS,
  937.                 short& whichBreak,
  938.                 const VRect& theViewArea,
  939.                 TView* theView) :
  940.         fOrthoVHS(theOrthoVHS),
  941.         fVHS(theVHS),
  942.         fWhichBreak(whichBreak),
  943.         fViewArea(theViewArea),
  944.         fView(theView)
  945.     {
  946.     }
  947.  
  948.     pascal Boolean DrawABreak(VCoordinate loc,
  949.                               Boolean automatic);
  950. };
  951.  
  952. #pragma segment PrintRes
  953. pascal Boolean CPageBreaks::DrawABreak(VCoordinate loc,
  954.                                        Boolean automatic)
  955. {
  956.     if (loc > fViewArea[botRight][fOrthoVHS])
  957.         return TRUE;
  958.     else
  959.     {
  960.         ++fWhichBreak;
  961.         if (loc > (fViewArea[topLeft][fOrthoVHS] -  gBreaksPenState.pnSize[fOrthoVHS]))
  962.             fView->DoDrawPageBreak(fVHS, fWhichBreak, loc, automatic);
  963.         return FALSE;
  964.     }
  965. }
  966.  
  967. #pragma segment PrintRes
  968. // Draws page breaks and page numbers 
  969. pascal void TStdPrintHandler::DrawPrintFeedback(const VRect& area)    // override 
  970. {
  971.     if (qDebug)
  972.         fView->AssumeFocused();
  973.     if (fShowBreaks || gDebugPrinting)
  974.     {
  975.         VHSelect vhs;
  976.         VHSelect orthoVHS;
  977.         short whichBreak = 0;
  978.         CPageBreaks aPageBreak(orthoVHS, vhs, whichBreak, area, fView);
  979.  
  980.         this->SetPrintExtent();                    // Make sure print extent is accurate before starting
  981. #if qDebug
  982.         if (gDebugPrinting)                        // Now draw Page numbers in the corners of pages, if desired
  983.         {
  984.             TextStyle pageNumStyle;
  985.  
  986.             SetTextStyle(pageNumStyle, applFont, bold, 9, gRGBBlack);
  987.             SetPortTextStyle(pageNumStyle);
  988.         }
  989. #endif
  990.  
  991.         SetPenState(gBreaksPenState);
  992.  
  993.         for (vhs = vSel; vhs <= hSel; ++vhs)
  994.         {
  995.             orthoVHS = gOrthogonal[vhs];
  996.             whichBreak = 0;
  997.             this->EachBreak(vhs, FALSE, (DoToBreakType) & CPageBreaks::DrawABreak, &aPageBreak);
  998.         }
  999.     }
  1000. }
  1001.  
  1002. //--------------------------------------------------------------------------------------------------
  1003. #pragma segment PrintRes
  1004.  
  1005. #if qDebug
  1006. pascal void TStdPrintHandler::DrawPageBreak(VHSelect vhs,
  1007.                                             long whichBreak,
  1008.                                             VCoordinate loc,
  1009.                                             Boolean)// override 
  1010. #else
  1011. pascal void TStdPrintHandler::DrawPageBreak(VHSelect vhs,
  1012.                                             long/* whichBreak */,
  1013.                                             VCoordinate loc,
  1014.                                             Boolean)// multiple declarations to eliminate compiler warnings 
  1015. #endif
  1016.  
  1017. {
  1018.     VPoint vPt;
  1019.     Point qdStartPt;
  1020.     Point qdEndPt;
  1021.  
  1022.     vPt[gOrthogonal[vhs]] = loc;
  1023.     vPt[vhs] = 0;
  1024.     qdStartPt = fView->ViewToQDPt(vPt);
  1025.     vPt[vhs] = fView->fSize[vhs] - gBreaksPenState.pnSize[vhs];
  1026.     qdEndPt = fView->ViewToQDPt(vPt);
  1027.  
  1028.     if (fShowBreaks)
  1029.     {
  1030.         MoveTo(qdStartPt.h, qdStartPt.v);
  1031.         LineTo(qdEndPt.h, qdEndPt.v);
  1032.     }
  1033.  
  1034. #if qDebug
  1035.     if (gDebugPrinting)
  1036.         if (vhs == hSel)
  1037.         {
  1038.             VCoordinate hLoc;
  1039.             Str255 aString;
  1040.             FontInfo theFontInfo;
  1041.             Rect theTextRect;
  1042.  
  1043.             for (long i = 0; i <= fPageStrips.v; ++i)
  1044.             {
  1045.                 if (i == 0)
  1046.                     hLoc = 0;
  1047.                 else
  1048.                     this->GetBreakCoord(vSel, i, hLoc);
  1049.  
  1050.                 GetFontInfo(theFontInfo);
  1051.  
  1052.                 NumToString(this->StripToPage(whichBreak - 1, i), aString);
  1053.                 // top computed based on the bottom - text height
  1054.                 theTextRect = Rect(qdStartPt.v - 3 - theFontInfo.ascent, (short)hLoc + 3, qdStartPt.v - 3 + theFontInfo.descent, (short)hLoc + 3 + StringWidth(aString));
  1055.                 MADrawString(aString, theTextRect, teFlushDefault);
  1056.  
  1057.                 NumToString(this->StripToPage(whichBreak, i), aString);
  1058.                 // top computed based on the bottom - text height
  1059.                 theTextRect = Rect(qdEndPt.v + 10 - theFontInfo.ascent, (short)hLoc + 3, qdEndPt.v + 10 + theFontInfo.descent, (short)hLoc + 3 + StringWidth(aString));
  1060.                 MADrawString(aString, theTextRect, teFlushDefault);
  1061.  
  1062.                 NumToString(this->StripToPage(whichBreak - 1, i - 1), aString);
  1063.                 // top computed based on the bottom - text height
  1064.                 theTextRect = Rect(qdStartPt.v - 3 - theFontInfo.ascent, (short)hLoc - StringWidth(aString) - 3, qdStartPt.v - 3 + theFontInfo.descent, (short)hLoc - 3);
  1065.                 MADrawString(aString, theTextRect, teFlushDefault);
  1066.  
  1067.                 NumToString(this->StripToPage(whichBreak, i - 1), aString);
  1068.                 // top computed based on the bottom - text height
  1069.                 theTextRect = Rect(qdEndPt.v + 10 - theFontInfo.ascent, (short)hLoc - StringWidth(aString) - 3, qdEndPt.v + 10 + theFontInfo.descent, (short)hLoc - 3);
  1070.                 MADrawString(aString, theTextRect, teFlushDefault);
  1071.             }
  1072.         }
  1073. #endif
  1074.  
  1075. }
  1076.  
  1077. //--------------------------------------------------------------------------------------------------
  1078. #pragma segment PrintImage
  1079.  
  1080. pascal void TStdPrintHandler::DrawPageInterior(void)
  1081. {
  1082.     fView->DrawContents();                        // i.e., by default, the same code used for drawing on the screen
  1083. }
  1084.  
  1085. //--------------------------------------------------------------------------------------------------
  1086. #pragma segment PrintRes
  1087.  
  1088. pascal void TStdPrintHandler::EachBreak(VHSelect vhs,
  1089.                                         Boolean includeLast,
  1090.                                         DoToBreakType DoToBreak,
  1091.                                         void* staticLink)
  1092. {
  1093.     VCoordinate startLoc;
  1094.     VCoordinate endLoc;
  1095.     VCoordinate loc;
  1096.     Boolean automatic;
  1097.     Boolean done;
  1098.     VCoordinate prevBreak = 0;
  1099.  
  1100.     startLoc = fPrintExtent[topLeft][gOrthogonal[vhs]];
  1101.     endLoc = fPrintExtent[botRight][gOrthogonal[vhs]];
  1102.  
  1103.     loc = startLoc;
  1104.     automatic = TRUE;
  1105.     done = FALSE;
  1106.     while ((loc < endLoc) &&!done)
  1107.     {
  1108.         if (loc != startLoc)
  1109.             done = (*DoToBreak)(loc, automatic, staticLink);
  1110.         if (qDebug)
  1111.             prevBreak = loc;
  1112.  
  1113.         loc = fView->DoBreakFollowing(vhs, loc, automatic);
  1114.  
  1115.         if (qDebug && (loc <= prevBreak))
  1116.             ProgramBreak("thisBreak (loc) <= prevBreak");// Thanks much to Larry T. ! 
  1117.     }
  1118.  
  1119.     if (includeLast)
  1120.         (*DoToBreak)(loc, automatic, staticLink);
  1121. }
  1122.  
  1123. //--------------------------------------------------------------------------------------------------
  1124. #pragma segment PrintFields
  1125.  
  1126. pascal void TStdPrintHandler::Fields(TObject* obj)
  1127. {
  1128.     obj->DoToField("TStdPrintHandler", NULL, bClass);
  1129.     obj->DoToField("fPageAreas", NULL, bTitle);
  1130.     obj->DoToField("  thePaper", &fPageAreas.thePaper, bRect);
  1131.     obj->DoToField("  theInk", &fPageAreas.theInk, bRect);
  1132.     obj->DoToField("  theMargins", &fPageAreas.theMargins, bRect);
  1133.     obj->DoToField("  theInterior", &fPageAreas.theInterior, bRect);
  1134.     obj->DoToField("fPrintExtent", &fPrintExtent, bVRect);
  1135.     obj->DoToField("fFixedSizePages[h]", &fFixedSizePages[hSel], bBoolean);
  1136.     obj->DoToField("fFixedSizePages[v]", &fFixedSizePages[vSel], bBoolean);
  1137.     obj->DoToField("fHPrint", &fHPrint, bHandle);
  1138.     obj->DoToField("fPageStrips", &fPageStrips, bPoint);
  1139.     obj->DoToField("fStartPage", &fStartPage, bLongInt);
  1140.     obj->DoToField("fPrinterDev", &fPrinterDev, bLongInt);
  1141.     obj->DoToField("fLastPrinterName", &fLastPrinterName, bStringHandle);
  1142.     obj->DoToField("fPageDirection", &fPageDirection, bVHSelect);
  1143.     obj->DoToField("fShowBreaks", &fShowBreaks, bBoolean);
  1144.     obj->DoToField("fFinderSetup", &fFinderSetup, bBoolean);
  1145.     obj->DoToField("fFinderJobDialog", &fFinderJobDialog, bBoolean);
  1146.     obj->DoToField("fSquareDots", &fSquareDots, bBoolean);
  1147.     obj->DoToField("fMinimalMargins", &fMinimalMargins, bBoolean);
  1148.     obj->DoToField("fLastStrip", &fLastStrip, bPoint);
  1149.     obj->DoToField("fLastBreak", &fLastBreak, bVPoint);
  1150.     obj->DoToField("fViewedRect", &fViewedRect, bVRect);
  1151.     obj->DoToField("fMarginRes", &fMarginRes, bPoint);
  1152.     obj->DoToField("fPrintDialog", &fPrintDialog, bWindowPtr);// need a bDialogPtr 
  1153.  
  1154.     obj->DoToField("fPPrPort", NULL, bTitle);
  1155.     if (fPPrPort)
  1156.     {
  1157.         obj->DoToField("  gPort", &fPPrPort, bGrafPtr);
  1158.         obj->DoToField("  gProcs", &fPPrPort->gProcs, bQDProcs);
  1159.         obj->DoToField("  IGParam1", &fPPrPort->lGParam1, bLongInt);
  1160.         obj->DoToField("  IGParam2", &fPPrPort->lGParam2, bLongInt);
  1161.         obj->DoToField("  IGParam3", &fPPrPort->lGParam3, bLongInt);
  1162.         obj->DoToField("  IGParam4", &fPPrPort->lGParam4, bLongInt);
  1163.         obj->DoToField("  fOurPtr", &fPPrPort->fOurPtr, bBoolean);
  1164.         obj->DoToField("  fOurBits", &fPPrPort->fOurBits, bBoolean);
  1165.     }
  1166.     inherited::Fields(obj);
  1167. }
  1168.  
  1169. //--------------------------------------------------------------------------------------------------
  1170. #pragma segment PrintImage
  1171.  
  1172. pascal void TStdPrintHandler::FocusOnBorder(void)
  1173. {
  1174.     VRect rectToClipTo(fPageAreas.theInk);
  1175.     Rect qdRectToClipTo;
  1176.  
  1177.     // Only works for newer LaserWriter drivers 
  1178.     SetOrigin((short)fPageAreas.theInk.left, (short)fPageAreas.theInk.top);
  1179.     fView->ViewToQDRect(rectToClipTo, qdRectToClipTo);
  1180.     ClipRect(qdRectToClipTo);
  1181. }
  1182.  
  1183. //--------------------------------------------------------------------------------------------------
  1184. #pragma segment PrintImage
  1185.  
  1186. pascal void TStdPrintHandler::FocusOnInterior(void)// override 
  1187. {
  1188.     VRect rectToClip;
  1189.     VRect aRect;
  1190.     VPoint theOrigin;
  1191.     VPoint theVOrigin;
  1192.     VRect aVRect;
  1193.     Rect qdRectToClip;
  1194.  
  1195.     aRect = fPageAreas.theInk;
  1196.     theOrigin = fPageAreas.theInk[topLeft];
  1197.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  1198.         if (fView->fSize[vhs] > kMaxCoord)
  1199.             theVOrigin[vhs] = gPageOffset[vhs];
  1200.         else
  1201.         {
  1202.             theVOrigin[vhs] = 0;
  1203.             theOrigin[vhs] = theOrigin[vhs] + gPageOffset[vhs];
  1204.             aRect[topLeft][vhs] = aRect[topLeft][vhs] + gPageOffset[vhs];
  1205.             aRect[botRight][vhs] = aRect[botRight][vhs] + gPageOffset[vhs];
  1206.         }
  1207.     SetOrigin((short)theOrigin.h, (short)theOrigin.v);
  1208.     fView->fViewToQDOffset = theVOrigin;
  1209.  
  1210.     // Clip the page to the intersection of the visible part of the view and the
  1211.     // printable area of the page.  Note that in some cases (e.g., a WYSIWYG
  1212.     // word processor which showed the complete page margin) parts of
  1213.     // the interior might lie outside theInk.  We must clip to theInk to
  1214.     // avoid slowing down PostScript printers.
  1215.     rectToClip = fViewedRect & aRect;
  1216.     fView->ViewToQDRect(rectToClip, qdRectToClip);
  1217.     ClipRect(qdRectToClip);
  1218. }
  1219.  
  1220. //--------------------------------------------------------------------------------------------------
  1221. #pragma segment PrintRes
  1222.  
  1223. pascal void TStdPrintHandler::GetBreakCoord(VHSelect vhs,
  1224.                                             long whichBreak,
  1225.                                             VCoordinate& loc)
  1226. {
  1227.     Boolean automatic;
  1228.     long startBreak;
  1229.     VHSelect orthoVHS;
  1230.     VCoordinate prevBreak = 0;
  1231.  
  1232.  
  1233.     orthoVHS = gOrthogonal[vhs];
  1234.     if (fFixedSizePages[orthoVHS])
  1235.         loc = fPrintExtent[topLeft][orthoVHS] + fViewPerPage[orthoVHS] * whichBreak;
  1236.     else if (whichBreak == fLastStrip[vhs])
  1237.         loc = fLastBreak[vhs];
  1238.     else
  1239.     {
  1240.         if (whichBreak > fLastStrip[vhs])
  1241.         {
  1242.             startBreak = fLastStrip[vhs] + 1;
  1243.             loc = fLastBreak[vhs];
  1244.         }
  1245.         else
  1246.         {
  1247.             startBreak = 1;
  1248.             loc = fPrintExtent[topLeft][gOrthogonal[vhs]];
  1249.         }
  1250.  
  1251.         for (long i = startBreak; i <= whichBreak; ++i)
  1252.         {
  1253.             if (qDebug)
  1254.                 prevBreak = loc;
  1255.  
  1256.             loc = fView->DoBreakFollowing(vhs, loc, automatic);// ??? error handling??? 
  1257.  
  1258.             if (qDebug && (loc <= prevBreak))
  1259.                 ProgramBreak("thisBreak (loc) <= prevBreak");
  1260.         }
  1261.     }
  1262.     loc = Min(loc, fPrintExtent[botRight][orthoVHS]);
  1263.  
  1264.     fLastStrip[vhs] = whichBreak;
  1265.     fLastBreak[vhs] = loc;
  1266. }
  1267.  
  1268. //--------------------------------------------------------------------------------------------------
  1269. #pragma segment PrintActual
  1270.  
  1271. pascal void TStdPrintHandler::GetDocName(Str255& docName)
  1272. {
  1273.     TView * aView;
  1274.  
  1275.     if (fDocument)
  1276.         fDocument->GetTitle(docName);
  1277.     if (docName.IsEmpty())
  1278.     {
  1279.         aView = fView->GetRootView();
  1280.         if (aView && aView->IsMemberClass(GetClassIDFromName("TWindow")))
  1281.             ((TWindow *)aView)->GetTitle(docName);
  1282.     }
  1283. #if qDebug
  1284.     if (docName.IsEmpty())
  1285.         ProgramBreak("GetDocName can''t get a document or window name");
  1286. #endif
  1287.  
  1288. }
  1289.  
  1290. //--------------------------------------------------------------------------------------------------
  1291. #pragma segment PrintMain
  1292.  
  1293. pascal Handle TStdPrintHandler::GetPrintInfo(void)
  1294. {
  1295.     return fHPrint;
  1296. }
  1297.  
  1298. //--------------------------------------------------------------------------------------------------
  1299. #pragma segment PrintNonRes
  1300.  
  1301. pascal void TStdPrintHandler::InstallMargins(const VRect& newMargins,
  1302.                                              Boolean areMinimalMargins)
  1303. {
  1304.     fMinimalMargins = areMinimalMargins;
  1305.  
  1306.     if (fMinimalMargins)
  1307.     {
  1308.         fPageAreas.theMargins = fPageAreas.theInk;
  1309.         fPageAreas.theMargins[topLeft] -= fPageAreas.thePaper[topLeft];
  1310.         fPageAreas.theMargins[botRight] -= fPageAreas.thePaper[botRight];
  1311.         fPageAreas.theInterior = fPageAreas.theInk;
  1312.     }
  1313.     else
  1314.     {
  1315.         fPageAreas.theMargins = newMargins;
  1316.         fPageAreas.theInterior = fPageAreas.thePaper;
  1317.         fPageAreas.theInterior[topLeft] += fPageAreas.theMargins[topLeft];
  1318.         fPageAreas.theInterior[botRight] += fPageAreas.theMargins[botRight];
  1319.     }
  1320. }
  1321.  
  1322. //--------------------------------------------------------------------------------------------------
  1323. #pragma segment PrintNonRes
  1324.  
  1325. pascal void TStdPrintHandler::InvalPageFeedback(void)
  1326. {
  1327.     if (this->ShowsOnScreen())
  1328.         fView->ForceRedraw();
  1329. }
  1330.  
  1331. //--------------------------------------------------------------------------------------------------
  1332. #pragma segment PrintNonRes
  1333.  
  1334. pascal void TStdPrintHandler::LocatePageInterior(long,
  1335.                                                  VPoint& loc)// override 
  1336. {
  1337.     loc = fPageAreas.thePaper[topLeft];
  1338.     loc += fPageAreas.theMargins[topLeft];
  1339. }
  1340.  
  1341. //--------------------------------------------------------------------------------------------------
  1342. #pragma segment PrintActual
  1343.  
  1344. pascal long TStdPrintHandler::MaxPageNumber(void)// override 
  1345.  
  1346. {
  1347.     return fStartPage + (fPageStrips.v * fPageStrips.h) - 1;
  1348. }
  1349.  
  1350. //--------------------------------------------------------------------------------------------------
  1351. #pragma segment PrintActual
  1352.  
  1353. pascal void TStdPrintHandler::OneSubJob(long subjobFirstPage,
  1354.                                         long subjobLastPage,
  1355.                                         Boolean justSpool,
  1356.                                         Boolean,
  1357.                                         Boolean& ranOutOfSpace,
  1358.                                         long& lastPageTried,
  1359.                                         Boolean& proceed)
  1360. {
  1361.     long noOfCopies;
  1362.     OSErr err;
  1363.     TPrJob & printJob = ((TPPrint) * fHPrint)->prJob;
  1364.     FailInfo fi;
  1365.  
  1366.     VOLATILE(proceed);
  1367.  
  1368. #if qDebugMsg
  1369.     if (gDebugPrinting)
  1370.         fprintf(stderr, "OneSubJob entered for pages %1d through %1d, proceed=%s\n",
  1371.                 subjobFirstPage, subjobLastPage, proceed ? "TRUE" : "FALSE");
  1372. #endif
  1373.  
  1374.     ranOutOfSpace = FALSE;
  1375.     lastPageTried = subjobFirstPage - 1;
  1376.  
  1377.     printJob.iFstPage = 1;
  1378.     printJob.iLstPage = (short)(subjobLastPage - subjobFirstPage + 1);
  1379.  
  1380.     if (printJob.bJDocLoop == bSpoolLoop)
  1381.         noOfCopies = 1;
  1382.     else
  1383.         noOfCopies = printJob.iCopies;
  1384.  
  1385.     fPPrPort = PrOpenDoc((THPrint)fHPrint, NULL, NULL);
  1386.     // ??? need to allow/encourage app to supply nonNil args? 
  1387.     this->ChkPrintErr(err, proceed, ranOutOfSpace);
  1388.     gCurrPrintHandler = this;
  1389.  
  1390.     if (proceed)
  1391.     {
  1392.         fView->InvalidateFocus();
  1393.         fView->UpdateCoordinates();
  1394.         gPrinting = TRUE;
  1395.         SetPort((GrafPtr)fPPrPort);
  1396.         fView->BeInPort((GrafPtr)fPPrPort);
  1397.  
  1398.         gPrinting = TRUE;
  1399.         if (!fView->Focus())
  1400.         {
  1401. #if qDebug
  1402.             ProgramBreak("Can''t focus view while printing");
  1403. #endif
  1404.  
  1405.         }
  1406.         for (long pass = 1; pass <= noOfCopies; ++pass)
  1407.             for (long aPageNumber = subjobFirstPage; aPageNumber <= subjobLastPage; ++aPageNumber)
  1408.                 if (proceed)
  1409.                 {
  1410.                     lastPageTried = aPageNumber;
  1411.                     if (fi.Try())
  1412.                     {
  1413.                         this->PrintPage(aPageNumber);
  1414.                         fi.Success();
  1415.                     }
  1416.                     else    // Recover
  1417.                     {
  1418.                         proceed = FALSE;
  1419.                         err = fi.error;            // pass along client's error code Why???
  1420.                     }
  1421.                     this->ChkPrintErr(err, proceed, ranOutOfSpace);
  1422.                 }
  1423.         gPrinting = FALSE;
  1424.         fView->InvalidateFocus();
  1425.         fView->UpdateCoordinates();
  1426.         fView->BeInPort(fView->GetGrafPort());
  1427.     }
  1428.  
  1429.     gCurrPrintHandler = NULL;
  1430.     PrCloseDoc(fPPrPort);                        // This will close the port! 
  1431.     SetPort(gWorkPort);
  1432.     this->ChkPrintErr(err, proceed, ranOutOfSpace);
  1433.  
  1434.     if (ranOutOfSpace)
  1435.         return;
  1436.     else if (proceed)
  1437.     {
  1438.         if (((TPPrint) * fHPrint)->prJob.bJDocLoop == bSpoolLoop)
  1439.             if (!justSpool)
  1440.                 this->PrintSpoolFile(fHPrint, err, proceed);
  1441.     }
  1442.     if (!proceed)
  1443.         if (err != iPrAbort)
  1444.             Failure(err, 0);
  1445. }
  1446.  
  1447. //--------------------------------------------------------------------------------------------------
  1448. #pragma segment PrintRes
  1449.  
  1450. pascal void TStdPrintHandler::OpenPrintShop(void)
  1451. {
  1452.     OSErr err;
  1453.  
  1454.     PrOpen();                                    // Open the print shop 
  1455.     err = PrError();                            // Get code 
  1456.     if (err != noErr)
  1457.     {
  1458.         if ((err == fnfErr) || (err == resFNotFound))
  1459.             err = errNoPrintDrvr;
  1460.         Failure(err, 0);
  1461.     }
  1462. }
  1463.  
  1464. //--------------------------------------------------------------------------------------------------
  1465. #pragma segment PrintRes
  1466.  
  1467. pascal void TStdPrintHandler::PageToStrip(long pageNumber, VPoint& itsStrip)
  1468. {
  1469.     long normalizedPageNum;
  1470.     VHSelect ortho;
  1471.     VPoint strip;
  1472.  
  1473.     normalizedPageNum = pageNumber - fStartPage + 1;
  1474.  
  1475.     ortho = gOrthogonal[fPageDirection];
  1476.  
  1477.     itsStrip[ortho] = (normalizedPageNum - 1) / fPageStrips[ortho];
  1478.     itsStrip[fPageDirection] = normalizedPageNum - ((itsStrip[ortho]) * fPageStrips[ortho]) - 1;
  1479. }
  1480.  
  1481. //--------------------------------------------------------------------------------------------------
  1482. #pragma segment PrintRes
  1483.  
  1484. // !!! Need to test this! 
  1485. pascal void TStdPrintHandler::PointToPageStrip(const VPoint& pointInView, VPoint& pageStrip)
  1486. {
  1487.     long loc;
  1488.     Boolean automatic;
  1489.     VCoordinate prevBreak = 0;
  1490.  
  1491.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  1492.         if (fFixedSizePages[vhs])
  1493.             pageStrip[vhs] = (pointInView[vhs] / fViewPerPage[vhs]) + 1;
  1494.         else
  1495.         {
  1496.             pageStrip[vhs] = 1;
  1497.             loc = fPrintExtent[topLeft][vhs];    // ??? or orthogonal? 
  1498.             while (pointInView[vhs] > loc)
  1499.                 // ??? or orthogonal? 
  1500.                 {
  1501.                     if (qDebug)
  1502.                         prevBreak = loc;
  1503.  
  1504.                     loc = fView->DoBreakFollowing(vhs, loc, automatic);
  1505.  
  1506.                     if (qDebug && (loc <= prevBreak))
  1507.                         ProgramBreak("thisBreak (loc) <= prevBreak");
  1508.  
  1509.                     pageStrip[vhs]++;            // ??? Check the pascal.  This may be wrong. !!!
  1510.                 }
  1511.         }
  1512. }
  1513.  
  1514. //--------------------------------------------------------------------------------------------------
  1515. #pragma segment PrintActual
  1516.  
  1517. class CPrintDialogs
  1518. {
  1519.     Boolean& fResult;
  1520.     Handle fHPrint;
  1521.  
  1522. public:
  1523.     CPrintDialogs(Boolean& proceed,
  1524.                   Handle printHandle) :
  1525.         fResult(proceed),
  1526.         fHPrint(printHandle)
  1527.     {
  1528.     }
  1529.  
  1530.     pascal void CallJobDialog(void);
  1531.  
  1532.     pascal void CallStyleDialog(void);
  1533.  
  1534.     pascal void CallPrValidate(void);
  1535. };
  1536.  
  1537. #pragma segment PrintActual
  1538. pascal void CPrintDialogs::CallJobDialog(void)
  1539. {
  1540.     SetCursor(qd.arrow);
  1541.     if (gApplication)
  1542.         gApplication->InvalidateMouseRegions();
  1543.  
  1544.     fResult = PrJobDialog((THPrint)fHPrint);
  1545. }
  1546.  
  1547. #pragma segment PrintActual
  1548. pascal void CPrintDialogs::CallStyleDialog(void)
  1549. {
  1550.     SetCursor(qd.arrow);
  1551.     if (gApplication != NULL)
  1552.         gApplication->InvalidateMouseRegions();
  1553.  
  1554.     fResult = PrStlDialog((THPrint)fHPrint);
  1555. }
  1556.  
  1557. #pragma segment PrintActual
  1558. pascal void CPrintDialogs::CallPrValidate(void)
  1559. {
  1560.     fResult = PrValidate((THPrint)fHPrint);
  1561. }
  1562.  
  1563. #pragma segment PrintActual
  1564. pascal Boolean TStdPrintHandler::PoseJobDialog(void)
  1565. {
  1566.     Boolean b;
  1567.     Boolean proceed;
  1568.     OSErr err;
  1569.     CPrintDialogs aJobDialog(proceed, fHPrint);
  1570.  
  1571.     proceed = TRUE;
  1572.     // PrepareForDialog; 
  1573.     this->DoInMacPrint((WhatToDoType) & CPrintDialogs::CallJobDialog, &aJobDialog);
  1574.     this->ChkPrintErr(err, proceed, b);
  1575.     // Rectify the range as a public service if needed
  1576.     TPrJob & printJob = ((TPPrint) * fHPrint)->prJob;
  1577.     if (printJob.iFstPage > printJob.iLstPage)
  1578.     {
  1579.         short temp;
  1580.  
  1581.         temp = printJob.iLstPage;
  1582.         printJob.iLstPage = printJob.iFstPage;
  1583.         printJob.iFstPage = temp;
  1584.     }
  1585.     gApplication->UpdateAllWindows();
  1586.     return proceed;
  1587. }
  1588.  
  1589. //--------------------------------------------------------------------------------------------------
  1590. #pragma segment PrintActual
  1591. // Needs to be here because it may be called from Print
  1592.  
  1593. pascal void TStdPrintHandler::PosePageSetupDialog(Boolean& proceed,
  1594.                                                   Boolean isUndoable)
  1595. {
  1596.     Boolean react;
  1597.     TPrintStyleChangeCommand * aPrintStyleChangeCommand;
  1598.     CPrintDialogs aPageSetupDialog(react, fHPrint);
  1599.  
  1600.     react = FALSE;                                // in case MacPrint code not accessible 
  1601.     if (!isUndoable)
  1602.     {
  1603.         // PrepareForDialog; 
  1604.         this->DoInMacPrint((WhatToDoType) & CPrintDialogs::CallStyleDialog, &aPageSetupDialog);
  1605.         if (react)
  1606.             this->CheckPrinter();
  1607.     }
  1608.     else
  1609.     {
  1610.         // Must setup command before putting up page setup dialog because the
  1611.         // command records the current print record to make it undoable.
  1612.         aPrintStyleChangeCommand = new TPrintStyleChangeCommand;
  1613.         aPrintStyleChangeCommand->IPrintStyleChangeCommand(this);
  1614.  
  1615.         // Put up the Page Setup Dialog 
  1616.         this->DoInMacPrint((WhatToDoType) & CPrintDialogs::CallStyleDialog, &aPageSetupDialog);
  1617.         if (react)                                // User specified a change 
  1618.         {
  1619.             BlockMove((Ptr) * fHPrint, (Ptr) * (aPrintStyleChangeCommand->fNewHPrint), sizeof(TPrint));
  1620.             if (fView)
  1621.                 fView->PostCommand(aPrintStyleChangeCommand);    // !!! maybe we should fix fNextHandler instead
  1622.         }
  1623.         else                                    // User did not specify a change 
  1624.             aPrintStyleChangeCommand = (TPrintStyleChangeCommand *)FreeIfObject(aPrintStyleChangeCommand);
  1625.     }
  1626.     proceed = react;
  1627. }
  1628.  
  1629. //--------------------------------------------------------------------------------------------------
  1630. #pragma segment PrintActual
  1631.  
  1632. pascal void TStdPrintHandler::PosePrintDialog(void)
  1633. {
  1634.     short dlgNumber;
  1635.     DialogTHndl dlogTemplate;
  1636.     Str255 docName;
  1637.     short itemNo;
  1638.     Handle theItem;
  1639.     short itemType;
  1640.     Rect box;
  1641.     Str255 itemText;
  1642.     short preDocName,
  1643.      constTitle;
  1644.  
  1645.     /*### need to determine if multiple file printing is in process
  1646.       if (gFinderPrinting)
  1647.       {
  1648.       dlgNumber = phFinderPrintDialog;
  1649.       itemNo = 3;
  1650.       }
  1651.       else
  1652.       {
  1653.       dlgNumber = phSpoolPrintDialog;
  1654.       itemNo = 2;
  1655.       }
  1656.     */
  1657.     dlgNumber = phSpoolPrintDialog;
  1658.     itemNo = 2;
  1659.  
  1660.     // Can't use GetNewCenteredDialog because vertically centering the dialog may cause it
  1661.     // to interfere with the Print Manager's status windows.  Therefore, leave the vertical
  1662.     // location of the dialog fixed.
  1663.  
  1664.     SetCursor(qd.arrow);
  1665.     gApplication->InvalidateMouseRegions();
  1666.     dlogTemplate = (DialogTHndl)GetResource('DLOG', dlgNumber);
  1667.     if (dlogTemplate)
  1668.     {
  1669.         CenterRectOnScreen((*dlogTemplate)->boundsRect, TRUE, FALSE, FALSE);
  1670.         fPrintDialog = GetNewDialog(dlgNumber, (Ptr)NULL, (WindowPtr) - 1);
  1671.         FailNIL(fPrintDialog);
  1672.     }
  1673.     else
  1674.     {
  1675. #if qDebugMsg
  1676.         fprintf(stderr, "You may have forgotten to include Printing.rsrc in your .r file…\n");
  1677.         ProgramBreak("The print job dialog resource can''t be found.");
  1678. #endif
  1679.  
  1680.         FailNILResource((Handle)dlogTemplate);
  1681.     }
  1682.  
  1683.     // Substitute the document name for '<<!=>>' in 'Document “<<!=>>” is being printed'.
  1684.     // ParamText would be a lot simpler, but the Print Mgr. also uses ParamText, and
  1685.     // the substitution doesn't happen until draw time.
  1686.     this->GetDocName(docName);
  1687.     GetDItem(fPrintDialog, itemNo, itemType, theItem, box);
  1688.     if (theItem)
  1689.     {
  1690.         GetIText(theItem, itemText);
  1691.         if (ParseTitleTemplate(itemText, preDocName, constTitle) && SubstituteInTitle(itemText, docName, preDocName, constTitle))
  1692.             SetIText(theItem, itemText);
  1693.     }
  1694.  
  1695.     ((TPPrint) * fHPrint)->prJob.pIdleProc = &IdleProcForTStdPrintHandler;
  1696.     SetWTitle(fPrintDialog, docName);            // In case Print Mgr. needs it. 
  1697.     DrawDialog(fPrintDialog);
  1698. }
  1699.  
  1700. //--------------------------------------------------------------------------------------------------
  1701. // ???Was in PrintActual.  Doesn't really belong in this segment,
  1702. //but can get unloaded during Finder printing otherwise.
  1703. #pragma segment PrintRes
  1704.  
  1705. pascal void TStdPrintHandler::Print(CmdNumber itsCmdNumber,
  1706.                                     Boolean& proceed)// override 
  1707. {
  1708.     FailInfo fi;
  1709.  
  1710.     gCancelAllPrinting = FALSE;
  1711.  
  1712.     this->SetPrintExtent();                        // Make sure we've got the right area. 
  1713.  
  1714.     if (fi.Try())
  1715.     {
  1716.         if (gCouldPrint)
  1717.         {
  1718.             long firstPage;
  1719.             long lastPage;
  1720.             OSErr err;
  1721.             Str255 spoolFileName;
  1722.             short spoolVRefNum;
  1723.             TPrJob aPrJob = ((TPPrint) * fHPrint)->prJob;
  1724.             long totalPages;
  1725.             long lastPrinted;
  1726.             long lastAttempted;
  1727.             long pagesPerSubjob;
  1728.             long firstSubjobPage;
  1729.             Boolean proceed = TRUE;
  1730.             Boolean ranOutOfSpace = FALSE;
  1731.             Boolean spoolMethod;
  1732.             Boolean justSpool = (itsCmdNumber == cPrintToFile);
  1733.             VPoint pageStrips;
  1734.             FailInfo fi;
  1735.  
  1736.             PrSetError(noErr);                    // Clear printer-error flag 
  1737.             this->OpenPrintShop();
  1738.             gJobPrintHandler = this;            // be visible to the idleProc 
  1739.             fView->DoCalcPageStrips(pageStrips);
  1740.             fPageStrips = pageStrips;
  1741.  
  1742.             firstPage = Max(aPrJob.iFstPage, fStartPage);
  1743.             lastPage = Min(aPrJob.iLstPage, this->MaxPageNumber());
  1744.  
  1745.             if (lastPage < firstPage)
  1746.                 err = Alert(phNoPages, NULL);
  1747.             else
  1748.             {
  1749.                 totalPages = lastPage - firstPage + 1;
  1750.                 spoolMethod = (aPrJob.bJDocLoop == bSpoolLoop);
  1751.                 if (spoolMethod)
  1752.                 {
  1753.                     this->ChooseSpoolFile(spoolFileName, spoolVRefNum, pagesPerSubjob);
  1754.                     // if justSpool is true, then the spool filename and vRefNum will already
  1755.                     // have been stuffed into the prJob record before this method is called
  1756.                     if (!justSpool)
  1757.                     {
  1758.                         if (!spoolFileName.IsEmpty())
  1759.                         {
  1760.                             aPrJob.pFileName = &spoolFileName;
  1761.                             aPrJob.iFileVol = spoolVRefNum;
  1762.                         }
  1763.                     }
  1764.                 }
  1765.                 else
  1766.                     pagesPerSubjob = MAXINT;
  1767.  
  1768.                 lastPrinted = firstPage - 1;
  1769.  
  1770.                 pagesPerSubjob = Min(pagesPerSubjob, totalPages);
  1771.                 this->PosePrintDialog();
  1772.  
  1773.                 if (fi.Try())
  1774.                 {
  1775.                     do
  1776.                     {
  1777.                         firstSubjobPage = lastPrinted + 1;
  1778.                         this->OneSubJob(firstSubjobPage, firstSubjobPage + pagesPerSubjob - 1, justSpool, (pagesPerSubjob < totalPages), ranOutOfSpace, lastAttempted, proceed);
  1779.                         if (proceed)
  1780.                             lastPrinted = lastAttempted;
  1781.                         if (ranOutOfSpace)
  1782.                         {
  1783.                             pagesPerSubjob = lastAttempted - 1 - firstSubjobPage;
  1784.                             proceed = TRUE;
  1785.                         }
  1786.                     } while ((lastPrinted != lastPage) && (pagesPerSubjob >= 1) && proceed);
  1787.  
  1788.                     if (pagesPerSubjob < 1)
  1789.                         Failure(errSpooling, 0);
  1790.                     fi.Success();
  1791.                 }
  1792.                 else
  1793.                 {
  1794.                     this->BanishPrintDialog();
  1795.                     fi.ReSignal();
  1796.                 }
  1797.                 this->BanishPrintDialog();        // having removed, put back here, unsure if exactly right
  1798.             }                                    // if there are pages within requested range
  1799.             gJobPrintHandler = NULL;            // out damned spot 
  1800.         }
  1801.         this->ClosePrintShop();
  1802.         SetPort(gWorkPort);                        // Might be left looking at a dead port 
  1803.         gApplication->InvalidateFocus();
  1804.         fi.Success();
  1805.     }
  1806.     else    // Recover
  1807.     {
  1808.         this->ClosePrintShop();
  1809.         SetPort(gWorkPort);                        // Might be left looking at a dead port 
  1810.         gApplication->InvalidateFocus();
  1811.  
  1812.         // Certain Print Manager errors should not result in any alert,
  1813.         // since the Print Manager will have already put one up.
  1814.         if ((fi.error >= -8160) && (fi.error <= -8150))
  1815.             Failure(0, msgPrintFailed);
  1816.         if (fi.message == 0)
  1817.             this->GetDocName(gErrorParm3);
  1818.         FailNewMessage(fi.error, fi.message, msgPrintFailed);
  1819.         fi.ReSignal();
  1820.     }
  1821.     proceed =!gCancelAllPrinting;
  1822. }
  1823.  
  1824. //--------------------------------------------------------------------------------------------------
  1825. #pragma segment PrintNonRes
  1826.  
  1827. pascal void TStdPrintHandler::PrinterChanged(void)// override 
  1828. {
  1829.     fView->DoPagination();
  1830. }
  1831.  
  1832. //--------------------------------------------------------------------------------------------------
  1833. #pragma segment PrintImage
  1834.  
  1835. pascal void TStdPrintHandler::PrintPage(long aPageNumber)// Print a single page 
  1836. {
  1837.     FailInfo fi;
  1838.  
  1839.     this->SetPage(aPageNumber);                    // gets gPage set up correctly for coordinate transformations
  1840.     if (fi.Try())
  1841.     {
  1842. #if qDebug
  1843.         GrafPtr aPort;
  1844. #endif
  1845.  
  1846.         PrOpenPage(fPPrPort, NULL);
  1847.         FailOSErr(PrError());
  1848.         this->FocusOnInterior();
  1849.         this->DrawPageInterior();
  1850. #if qDebug
  1851.         GetPort(aPort);
  1852.         if (aPort != ((GrafPtr)fPPrPort))
  1853.             ProgramBreak("The view''s DrawPageInterior method changed the grafPort");
  1854. #endif
  1855.  
  1856.         FailOSErr(PrError());
  1857.         this->FocusOnBorder();
  1858.         this->AdornPage();
  1859.         FailOSErr(PrError());
  1860.         fi.Success();
  1861.     }
  1862.     else    // Recover
  1863.     {
  1864.         PrClosePage(fPPrPort);
  1865.         fi.ReSignal();
  1866.     }
  1867.     PrClosePage(fPPrPort);
  1868. }
  1869.  
  1870. //--------------------------------------------------------------------------------------------------
  1871. #pragma segment PrintNonRes
  1872.  
  1873. // Called from fView.DoPagination. 
  1874. pascal void TStdPrintHandler::RedoPageBreaks(void)// override 
  1875. {
  1876.     Boolean worryAboutBreaks;
  1877.     VPoint oldViewPerPage,  viewPerPage;
  1878.     VPoint pageStrips;
  1879.     VRect newInterior,  oldInterior;
  1880.  
  1881.     worryAboutBreaks = (fView->GetGrafPort()) && gInitialized && (fShowBreaks || gDebugPrinting);
  1882.  
  1883.     if (worryAboutBreaks)
  1884.         this->InvalPageFeedback();                // invalidate old page breaks, if relevant 
  1885.  
  1886.     this->SetPrintExtent();
  1887.     oldInterior = fPageAreas.theInterior;
  1888.     oldViewPerPage = fViewPerPage;
  1889.     this->SetMargins();
  1890.  
  1891.     // computes view per page from papersize, printer resolution, margins desired, view resolution,
  1892.     //and, if desired, other factors such as printable rectangle of page and font metrics in the
  1893.     //printer space
  1894.     fView->DoCalcViewPerPage(viewPerPage);
  1895.     fViewPerPage = viewPerPage;
  1896.     this->SetPageInterior(kUsualPages);
  1897.     newInterior = fPageAreas.theInterior;
  1898.  
  1899. #if qDebug
  1900.     if (gDebugPrinting)
  1901.         if (oldInterior != newInterior)
  1902.             ProgramBreak("Setting new interior");
  1903. #endif
  1904.  
  1905.     if (oldInterior != newInterior)
  1906.         fView->PageInteriorChanged(newInterior);
  1907.  
  1908. #if qDebug
  1909.     if (gDebugPrinting)
  1910.         if (oldViewPerPage != viewPerPage)
  1911.             ProgramBreak("Setting new view per page");
  1912. #endif
  1913.  
  1914.     if ((oldInterior != newInterior) || (oldViewPerPage != viewPerPage))
  1915.         fView->AdjustSize();
  1916.  
  1917.     fView->DoCalcPageStrips(pageStrips);
  1918.     fPageStrips = pageStrips;
  1919.  
  1920.     if (worryAboutBreaks)
  1921.         this->InvalPageFeedback();                // force redraw of new page breaks, if relevant
  1922. }
  1923.  
  1924. //--------------------------------------------------------------------------------------------------
  1925. #pragma segment PrintNonRes
  1926.  
  1927. pascal void CallPrintDefault(void* staticLink)
  1928. {
  1929.     PrintDefault(*((THPrint *)staticLink));
  1930. }
  1931.  
  1932.  
  1933. pascal void TStdPrintHandler::Reset(void)
  1934. {
  1935.     THPrint anHPrint = (THPrint)fHPrint;
  1936.     Boolean didChange;
  1937.     Boolean inited = FALSE;
  1938.     FailInfo fi;
  1939.  
  1940.     VOLATILE(inited);
  1941.     
  1942.     if (anHPrint)
  1943.     {
  1944.         if (gCouldPrint)
  1945.         {
  1946.             if (fi.Try())
  1947.             {
  1948.                 TXWord printerFlags;
  1949.  
  1950.                 this->DoInMacPrint(CallPrintDefault, &anHPrint);
  1951.                 if (fSquareDots)
  1952.                 {
  1953.                     printerFlags.iO = ((TPPrint) * fHPrint)->prStl.wDev;
  1954.                     if (printerFlags.byteVal.b1 == 1)// 1 == bDevCItoh => ImageWriter 
  1955.                     {
  1956.                         // Set the square-pixel flag in the print record, then
  1957.                         // ensure we didn't corrupt it.
  1958.                         printerFlags.boolVal.f2 = TRUE;
  1959.                         this->ValidatePrintRecord(didChange);
  1960.                     }
  1961.                 }
  1962.                 inited = TRUE;
  1963.                 fi.Success();
  1964.             }
  1965.         }
  1966.         // MacPrint code unavailable, but we want some plausible things
  1967.         // anyway - set up for Portrait Tall Adj.
  1968.         // ??? Replace the following expensive stuffing code with StuffHex
  1969.         // calls or a GetResource or some such, later
  1970.         if (!(gCouldPrint && inited))
  1971.         {
  1972.             (*anHPrint)->iPrVersion = 0;    // something invalid 
  1973.  
  1974.             (*anHPrint)->prInfo.iHRes = 72;
  1975.             (*anHPrint)->prInfo.iVRes = 72;
  1976.             (*anHPrint)->prInfo.rPage = Rect(0, 0, 752, 576);// must have its top left & (0,0)
  1977.  
  1978.             (*anHPrint)->rPaper = Rect(-36, -18, 756, 594);
  1979.             (*anHPrint)->prStl.iPageV = 1320;// 11 inches in 120th of an inch 
  1980.             (*anHPrint)->prStl.iPageH = 1020;// 8.5 inches in 120th of an inch 
  1981.         }
  1982.     }
  1983. }
  1984.  
  1985. //--------------------------------------------------------------------------------------------------
  1986. #pragma segment PrintNonRes
  1987.  
  1988. pascal void TStdPrintHandler::SetPrintExtent(void)
  1989. {
  1990.     VRect printExtent;
  1991.  
  1992.     fView->GetPrintExtent(printExtent);
  1993.     // Make sure the bottom or right is not smaller than the top or left.
  1994.     // This can happen when views are being created and before the window
  1995.     // has been resized to its actual size.
  1996.     printExtent.bottom = Max(printExtent.bottom, printExtent.top);
  1997.     printExtent.right = Max(printExtent.right, printExtent.left);
  1998.     fPrintExtent = printExtent;
  1999. }
  2000.  
  2001. //--------------------------------------------------------------------------------------------------
  2002. #pragma segment PrintOpen
  2003.  
  2004. pascal void TStdPrintHandler::SetDefaultPrintInfo(void)
  2005. {
  2006.     Boolean didChange;
  2007.     Boolean wantValidate = FALSE;
  2008.     Boolean haveHPrint = FALSE;
  2009.  
  2010.     fHPrint = DisposeIfHandle(fHPrint);
  2011.  
  2012.     if (fView)
  2013.     {
  2014.         if (fDocument && (fDocument->fSharePrintInfo && fDocument->fPrintInfo))
  2015.         {
  2016.             fHPrint = fDocument->fPrintInfo;
  2017.             haveHPrint = TRUE;
  2018.         }
  2019.     }
  2020.  
  2021.     if (haveHPrint)
  2022.         wantValidate = TRUE;
  2023.     else
  2024.     {
  2025.         fHPrint = NewPermHandle(sizeof(TPrint));
  2026.         this->Reset();
  2027.     }
  2028.  
  2029.     if (wantValidate)
  2030.         this->ValidatePrintRecord(didChange);
  2031. }
  2032.  
  2033. //--------------------------------------------------------------------------------------------------
  2034. #pragma segment PrintNonRes
  2035.  
  2036. pascal void TStdPrintHandler::SetMargins(void)
  2037. {
  2038.     VRect someMargins;
  2039.  
  2040.     someMargins = fPageAreas.theMargins;
  2041.     this->InstallMargins(someMargins, fMinimalMargins);
  2042. }
  2043.  
  2044. //--------------------------------------------------------------------------------------------------
  2045. #pragma segment PrintImage
  2046.  
  2047. pascal void TStdPrintHandler::SetPage(long aPageNumber)
  2048. {
  2049.     VRect viewedRect;
  2050.     VPoint strip;
  2051.  
  2052.     fFocusedPage = aPageNumber;
  2053.     this->PageToStrip(aPageNumber, strip);
  2054.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  2055.     {
  2056.         this->GetBreakCoord(gOrthogonal[vhs], strip[vhs], viewedRect[topLeft][vhs]);
  2057.         this->GetBreakCoord(gOrthogonal[vhs], strip[vhs] + 1, viewedRect[botRight][vhs]);
  2058.     }
  2059.  
  2060.     this->SetPageInterior(aPageNumber);
  2061.     fView->DoSetPageOffset(viewedRect[topLeft]);
  2062.     fViewedRect = viewedRect;
  2063.  
  2064. #if qDebugMsg
  2065.     if (gDebugPrinting)
  2066.         fprintf(stderr, "pg #: %1d; coord = %s Page Interior: %s\n",
  2067.                 aPageNumber, (char *) viewedRect[topLeft], (char *) fPageAreas.theInterior);
  2068. #endif
  2069.  
  2070. }
  2071.  
  2072. //--------------------------------------------------------------------------------------------------
  2073. #pragma segment PrintNonRes
  2074.  
  2075. pascal void TStdPrintHandler::SetPageInterior(long pageNumber)// override 
  2076. {
  2077.     VPoint pegPoint;
  2078.  
  2079.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  2080.     {
  2081.         fPageAreas.theInterior[topLeft][vhs] = fPageAreas.thePaper[topLeft][vhs] + fPageAreas.theMargins[topLeft][vhs];
  2082.         fPageAreas.theInterior[botRight][vhs] = fPageAreas.theInterior[topLeft][vhs] + fViewPerPage[vhs];
  2083.     }
  2084.  
  2085.     this->LocatePageInterior(pageNumber, pegPoint);
  2086.     fPageAreas.theInterior[topLeft] = pegPoint;
  2087.     for (vhs = vSel; vhs <= hSel; ++vhs)
  2088.         fPageAreas.theInterior[botRight][vhs] = fPageAreas.theInterior[topLeft][vhs] + fViewPerPage[vhs];
  2089. }
  2090.  
  2091. //--------------------------------------------------------------------------------------------------
  2092. #pragma segment PrintImage
  2093.  
  2094. pascal void TStdPrintHandler::SetPageOffset(const VPoint& coord)// override 
  2095. {
  2096.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  2097.         gPageOffset[vhs] = coord[vhs] - fPageAreas.theInterior[topLeft][vhs];
  2098. }
  2099.  
  2100. //--------------------------------------------------------------------------------------------------
  2101. #pragma segment PrintFinder
  2102.  
  2103. pascal Boolean TStdPrintHandler::SetupForFinder(void)// override 
  2104. {
  2105.     Boolean proceed;
  2106.     Boolean didChange;
  2107.  
  2108.     proceed = TRUE;
  2109.     this->CheckPrinter();                    // Uncertain if necessary??? 
  2110.  
  2111.     if (fFinderSetup)
  2112.         this->PosePageSetupDialog(proceed, FALSE);
  2113.  
  2114.     if (proceed)
  2115.     {
  2116.         this->ShowDocBeingPrinted(TRUE);
  2117.         if (fFinderJobDialog ||!gFinderHPrint)
  2118.         {
  2119.             proceed = this->PoseJobDialog();
  2120.             // Merge into gPrintHandler, in case next document needs it 
  2121.             if (!gFinderHPrint)
  2122.                 gFinderHPrint = NewPermHandle(sizeof(TPrint));
  2123.  
  2124.             BlockMove((*fHPrint), (*gFinderHPrint), sizeof(TPrint));
  2125.         }
  2126.         else
  2127.         {
  2128.             PrJobMerge((THPrint)gFinderHPrint, (THPrint)fHPrint);
  2129.             this->ValidatePrintRecord(didChange);
  2130.         }
  2131.         this->ShowDocBeingPrinted(FALSE);
  2132.     }
  2133.     return proceed;
  2134. }
  2135.  
  2136. //--------------------------------------------------------------------------------------------------
  2137. #pragma segment PrintRes
  2138.  
  2139. pascal Boolean TStdPrintHandler::SetupPrintOne(void)
  2140. {
  2141.     Boolean didChange;
  2142.  
  2143.     // Call PrValidate to 1) make sure the record is OK, and
  2144.     // 2) Get the LaserWriter driver to get the name of the front window.
  2145.     this->ValidatePrintRecord(didChange);
  2146.  
  2147.     PrSetError(noErr);
  2148.     ((TPPrint) * fHPrint)->prJob.iFstPage = 0;
  2149.     ((TPPrint) * fHPrint)->prJob.iLstPage = 9999;// This is what the Print Mgr. uses 
  2150.     return TRUE;                            // Should always be able to continue from here
  2151. }
  2152.  
  2153. //--------------------------------------------------------------------------------------------------
  2154. #pragma segment PrintFinder
  2155.  
  2156. pascal void TStdPrintHandler::ShowDocBeingPrinted(Boolean entering)
  2157. {
  2158.     Str255 aTitle;
  2159.  
  2160.     if (entering)
  2161.     {
  2162.         fPrintDialog = GetNewDialog(phWhichDoc, (Ptr)NULL, (WindowPtr) - 1);
  2163.         if (fPrintDialog)
  2164.         {
  2165.             this->GetDocName(aTitle);
  2166.             SetWTitle(fPrintDialog, aTitle);
  2167.             DrawDialog(fPrintDialog);
  2168.         }
  2169. #if qDebug
  2170.         else
  2171.         {
  2172.             Str255 theString;
  2173.             ConcatNumber("Unable to load dialog ", phWhichDoc, theString);
  2174.             ProgramBreak(theString);
  2175.         }
  2176. #endif
  2177.  
  2178.     }
  2179.     else
  2180.         this->BanishPrintDialog();
  2181. }
  2182.  
  2183. //--------------------------------------------------------------------------------------------------
  2184. #pragma segment PrintRes
  2185.  
  2186. pascal Boolean TStdPrintHandler::ShowsOnScreen(void)
  2187. {
  2188.     if (fView)
  2189.         return fView->IsVisible();
  2190.     else
  2191.         return FALSE;
  2192. }
  2193.  
  2194. //--------------------------------------------------------------------------------------------------
  2195. #pragma segment PrintRes
  2196.  
  2197. pascal long TStdPrintHandler::StripToPage(long hStrip,
  2198.                                           long vStrip)
  2199. {
  2200.     Point strip((short)vStrip, (short)hStrip);
  2201.     VHSelect ortho;
  2202.  
  2203.     ortho = gOrthogonal[fPageDirection];
  2204.     return strip[fPageDirection] * fPageStrips[ortho] + strip[ortho] + fStartPage;
  2205. }
  2206.  
  2207. //--------------------------------------------------------------------------------------------------
  2208. #pragma segment PrintRes
  2209.  
  2210. pascal void TStdPrintHandler::ValidatePrintRecord(Boolean& didChange)
  2211. {
  2212.     FailInfo fi;
  2213.     CPrintDialogs aPrValidateDialog(didChange, fHPrint);
  2214.  
  2215.     if (fi.Try())
  2216.     {
  2217.         this->DoInMacPrint((WhatToDoType) & CPrintDialogs::CallPrValidate, &aPrValidateDialog);
  2218.         fi.Success();
  2219.     }
  2220.     else    // Recover
  2221.         this->Reset();
  2222. }
  2223.  
  2224. //--------------------------------------------------------------------------------------------------
  2225. #pragma segment PrintDoCommand
  2226.  
  2227. pascal void TPrintStyleChangeCommand::Initialize(void)// override 
  2228. {
  2229.     inherited::Initialize();
  2230.     fNewHPrint = NULL;
  2231.     fOldHPrint = NULL;
  2232.     fStdPrintHandler = NULL;
  2233. }
  2234.  
  2235. //--------------------------------------------------------------------------------------------------
  2236. #pragma segment PrintDoCommand
  2237.  
  2238. pascal void TPrintStyleChangeCommand::IPrintStyleChangeCommand(TStdPrintHandler* itsPrintHandler)
  2239. {
  2240.     TDocument * changedDocument;
  2241.     FailInfo fi;
  2242.  
  2243.     changedDocument = itsPrintHandler->fDocument;
  2244.     this->ICommand(cChangePrinterStyle, changedDocument, itsPrintHandler->fView);
  2245.     fStdPrintHandler = itsPrintHandler;
  2246.     fCausesChange = (changedDocument && (changedDocument->fSavePrintInfo));
  2247.     if (fi.Try())
  2248.     {
  2249.         fOldHPrint = NewPermHandle(sizeof(TPrint));
  2250.         // Make a copy of the old version of the PrintInfo record 
  2251.         BlockMove(*(itsPrintHandler->fHPrint), *fOldHPrint, sizeof(TPrint));
  2252.         fNewHPrint = NewPermHandle(sizeof(TPrint));
  2253.         fi.Success();
  2254.     }
  2255.     else    // Recover
  2256.     {
  2257.         this->Free();
  2258.         fi.ReSignal();
  2259.     }
  2260. }
  2261.  
  2262. //--------------------------------------------------------------------------------------------------
  2263. #pragma segment PrintDoCommand
  2264.  
  2265. pascal void TPrintStyleChangeCommand::Free(void)// override 
  2266. {
  2267.     fOldHPrint = DisposeIfHandle(fOldHPrint);
  2268.     fNewHPrint = DisposeIfHandle(fNewHPrint);
  2269.     inherited::Free();
  2270. }
  2271.  
  2272. //--------------------------------------------------------------------------------------------------
  2273. #pragma segment PrintDoCommand
  2274.  
  2275. pascal void TPrintStyleChangeCommand::DoIt(void)// override 
  2276. {
  2277.     fStdPrintHandler->CheckPrinter();        // Will find it changed, and hence dispatch
  2278.     // to view's DoPrinterChanged
  2279. }
  2280.  
  2281. //--------------------------------------------------------------------------------------------------
  2282. #pragma segment PrintFields
  2283.  
  2284. pascal void TPrintStyleChangeCommand::Fields(TObject* obj)
  2285. {
  2286.     obj->DoToField("TPrintStyleChangeCommand", NULL, bClass);
  2287.     obj->DoToField("fStdPrintHandler", &fStdPrintHandler, bObject);
  2288.     obj->DoToField("fOldHPrint", &fOldHPrint, bHandle);
  2289.     obj->DoToField("fNewHPrint", &fNewHPrint, bHandle);
  2290.  
  2291.     inherited::Fields(obj);
  2292. }
  2293.  
  2294. //--------------------------------------------------------------------------------------------------
  2295. #pragma segment PrintDoCommand
  2296.  
  2297. pascal void TPrintStyleChangeCommand::UndoIt(void)// override 
  2298.  
  2299. {
  2300.     BlockMove(*fOldHPrint, *(fStdPrintHandler->fHPrint), sizeof(TPrint));
  2301.     fStdPrintHandler->CheckPrinter();        // Will find it changed, and hence dispatch
  2302.     // to view's DoPrinterChanged
  2303. }
  2304.  
  2305. //--------------------------------------------------------------------------------------------------
  2306. #pragma segment PrintDoCommand
  2307.  
  2308. pascal void TPrintStyleChangeCommand::RedoIt(void)// override 
  2309. {
  2310.     BlockMove(*fNewHPrint, *(fStdPrintHandler->fHPrint), sizeof(TPrint));
  2311.     fStdPrintHandler->CheckPrinter();        // Will find it changed, and hence dispatch
  2312.     // to view's DoPrinterChanged
  2313. }
  2314.  
  2315.  
  2316.